<?php
/**
 * FastApp.
 * 8/17/24
 * @Author 深色的海 (wx:deepsea_0024)
 * @Contact telegram:deepsea159
 */

namespace App\Mall\Api\Service;

use App\Fastapp\Exception\TipException;
use App\Mall\Model\MallGoodsSpec;
use App\Mall\Model\MallOrder;
use App\Mall\Model\MallOrderItem;
use Hyperf\DbConnection\Db;

class OrderService
{
    public function list(): array
    {
        return ['list' => MallOrder::query()->with(['item'])->where(['user_id' => get_uid()])->orderByDesc('id')->get()];
    }

    public function detail(int $id): array
    {
        $md = MallOrder::query()->with(['item'])->where(['id' => $id, 'user_id' => get_uid()])->firstOrFail();
        return $md->toArray();
    }

    public function unifiedorder(array $data): array
    {
        $uid = get_uid();
        $lock = $uid . md5(json_encode($data));
        if (!redis()->setnx($lock, '1')) throw new TipException(t('mall.order_repeat'));
        redis()->expire($lock, 120);
        $symbol = get_user_cache('symbol', $uid);
        $res = $this->calculatePrice($data, $symbol);
        Db::beginTransaction();
        try {
            $order = MallOrder::query()->create([
                'user_id' => $uid,
                'symbol' => $symbol,
                'no' => redis()->hIncrBy('gene', 'did', 1),
                'total_amount' => $res['total_amount'],
                'pay_amount' => $res['pay_amount'],
            ]);
            $in = [];
            foreach ($res['order_item'] as $item) {
                $item['order_id'] = $order->id;
                $item['symbol'] = $symbol;
                $item['sub_no'] = redis()->hIncrBy('gene', 'sid', 1);
                $in[] = $item;
            }
            MallOrderItem::query()->insert($in);
            Db::commit();
            return $order->toArray();
        } catch (\Throwable $throwable) {
            console()->error($throwable->getMessage());
            redis()->del($lock);
            Db::rollBack();
        }
        throw new TipException(fastapp_t('mall.order_failed'));
    }

    public function calculatePrice(array $data, string $symbol = ''): array
    {
        if (!$symbol) $symbol = get_user_cache('symbol');
        $item = $data['item'];
        $specIds = array_column($item, 'num', 'spec_id');
        $res = MallGoodsSpec::query()->with(['goods:id,name,images', 'price'])
            ->whereIn('id', array_keys($specIds))->get()->map(function ($item) {
                $item->prices = $item->price->pluck('price', 'symbol')->toArray();
                $item->goods->name = fastapp_lang_text($item->goods->name);
                $item->name = fastapp_lang_text($item->name);
                return $item;
            });
        $orderItem = [];
        foreach ($res as $spec) {
            $orderItem[] = [
                'goods_id' => $spec->goods_id,
                'price' => $spec->prices[$symbol],
                'num' => $specIds[$spec->id],
                'pay_amount' => bcmul($spec->prices[$symbol], (string)$specIds[$spec->id], 2),
                'cover' => $spec->goods->images[0] ?? '',
                'name' => $spec->goods->name,
                'spec' => $spec->name,
            ];
        }

        $total_amount = $pay_amount = array_sum(array_column($orderItem, 'pay_amount'));
        return ['order_item' => $orderItem, 'total_amount' => $total_amount, 'pay_amount' => $pay_amount];
    }
}